#pragma once

#include <queue>

class Machine
{
public:

	Machine(int capacity)
		:capacity(capacity)
	{
	}

	virtual ~Machine(void)
	{
	}

	bool WorkFinished()
	{
		return workUnits <= 0;
	}

	void MoveToNextTask()
	{				
		if(workItems.size() != 0)
		{
			workItems.pop();

			if(workItems.size() > 0)
			{
				workUnits = GetWorkUnits();
			}
		}
	}

	void DoWork()
	{
		workUnits--;
	}

	bool EnqueueWork(void* workItem)
	{
		if(HasMoreSpace())
		{
			workItems.push(workItem);

			if(workItems.size() == 1)
			{
				workUnits = GetWorkUnits();
			}

			return true;
		}
		else
		{
			return false;
		}
	}

	bool HasMoreSpace()
	{
		return workItems.size() < capacity;
	}

	int GetCount()
	{
		return workItems.size();
	}

	int GetCapacity()
	{
		return capacity;
	}

	bool HasTask()
	{
		return workItems.size() != 0;
	}

protected:
	void *GetCurrentWorkItem()
	{
		return workItems.front();
	}
	
	virtual int GetWorkUnits() = 0;
	
private:
	int capacity;

	int workUnits;
	std::queue<void *> workItems;


};

